#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Word数学公式合并器 - 专业版

一个专业的Word文档合并工具，专门用于将包含数学公式的文档
安全地合并到主文档中，确保数学公式完整显示且原始内容不被覆盖。

作者: AI助手
版本: 2.0
日期: 2024
"""

import os
import sys
import zipfile
import shutil
import tempfile
import re
from pathlib import Path


class WordMathMerger:
    """
    Word数学公式合并器类
    
    用于将包含数学公式的Word文档合并到主文档中，
    支持安全合并、数学公式修复、内容连续追加等功能。
    
    使用示例:
        merger = WordMathMerger()
        merger.merge("main.docx", "math.docx")
        
    高级用法:
        merger = WordMathMerger(backup=True, verbose=True)
        merger.merge_files("main.docx", "math.docx", "result.docx")
    """
    
    def __init__(self, backup=True, verbose=True, auto_cleanup=True):
        """
        初始化合并器
        
        Args:
            backup (bool): 是否创建备份文件，默认True
            verbose (bool): 是否显示详细日志，默认True
            auto_cleanup (bool): 是否自动清理旧的备份文件，默认True
        """
        self.backup = backup
        self.verbose = verbose
        self.auto_cleanup = auto_cleanup
        self.workspace = os.path.abspath(os.getcwd())  # 设置工作目录为当前执行目录
        
    def log(self, message):
        """日志输出"""
        if self.verbose:
            print(message)
    
    def _cleanup_backup_files(self, base_file=None):
        """自动清理备份文件
        
        Args:
            base_file (str, optional): 特定文件的备份，如果为None则清理所有.backup文件
        """
        if not self.auto_cleanup:
            return
            
        try:
            if base_file:
                # 清理特定文件的备份
                backup_file = f"{base_file}.backup"
                if os.path.exists(backup_file):
                    os.remove(backup_file)
                    self.log(f"🧹 已清理备份: {backup_file}")
            else:
                # 清理工作目录中的所有.backup文件
                backup_files = []
                for file in os.listdir(self.workspace):
                    if file.endswith('.backup'):
                        backup_files.append(os.path.join(self.workspace, file))
                
                if backup_files:
                    for backup_file in backup_files:
                        try:
                            os.remove(backup_file)
                            self.log(f"🧹 已清理备份: {os.path.basename(backup_file)}")
                        except Exception as e:
                            self.log(f"⚠️  清理备份失败: {backup_file} ({e})")
                    
                    self.log(f"🧹 共清理 {len(backup_files)} 个备份文件")
                    
        except Exception as e:
            self.log(f"⚠️  清理备份文件时出错: {e}")
            
    def merge(self, main_file, math_file, output_file=None):
        """
        合并两个Word文档
        
        Args:
            main_file (str): 主文档路径
            math_file (str): 要合并的文档路径
            output_file (str, optional): 输出文件路径，默认覆盖主文档
            
        Returns:
            bool: 合并是否成功
            
        Raises:
            FileNotFoundError: 文件不存在
            Exception: 合并过程中的其他错误
        """
        
        # 设置默认输出文件
        if output_file is None:
            output_file = main_file
            
        # 验证文件存在
        if not os.path.exists(main_file):
            raise FileNotFoundError(f"主文档不存在: {main_file}")
        if not os.path.exists(math_file):
            raise FileNotFoundError(f"要合并的文档不存在: {math_file}")
            
        self.log(f"🚀 开始合并文档...")
        self.log(f"📂 主文档: {main_file} ({os.path.getsize(main_file):,} 字节)")
        self.log(f"📂 要合并: {math_file} ({os.path.getsize(math_file):,} 字节)")
        
        try:
            with tempfile.TemporaryDirectory() as temp_dir:
                # 解压文档
                main_dir = self._extract_docx(main_file, temp_dir, "main")
                math_dir = self._extract_docx(math_file, temp_dir, "math")
                
                # 分析内容
                self._analyze_content(math_dir)
                
                # 执行合并
                self._merge_documents(main_dir, math_dir)
                
                # 创建输出文件
                self._create_output(main_dir, output_file)
                
                # 创建备份
                if self.backup and output_file == main_file:
                    backup_file = f"{main_file}.backup"
                    shutil.copy2(main_file, backup_file)
                    self.log(f"💾 备份已创建: {backup_file}")
                
                self.log(f"✅ 合并完成！")
                self.log(f"📊 最终文件: {output_file} ({os.path.getsize(output_file):,} 字节)")
                
                # 自动清理旧的备份文件
                self._cleanup_backup_files()
                
                return True
                
        except Exception as e:
            self.log(f"❌ 合并失败: {str(e)}")
            raise
    
    def merge_files(self, main_file, math_file, output_file):
        """合并文件并指定输出路径的便捷方法"""
        return self.merge(main_file, math_file, output_file)

    def merge_list(self, main_file, file_list, output_file=None):
        """
        合并文件列表到主文档
        
        Args:
            main_file (str): 主文档路径
            file_list (list): 要合并的文档路径列表
            output_file (str, optional): 输出文件路径，默认覆盖主文档
            
        Returns:
            bool: 合并是否全部成功
            
        示例：
            merger = WordMathMerger()
            files = ["math1.docx", "math2.docx", "math3.docx"]
            merger.merge_list("main.docx", files)
        """
        if not file_list:
            self.log("文件列表为空")
            return False
            
        if not os.path.exists(main_file):
            self.log(f"主文档不存在: {main_file}")
            return False
            
        # 确定输出文件
        if output_file and output_file != main_file:
            import shutil
            shutil.copy2(main_file, output_file)
            current_main = output_file
        else:
            current_main = main_file
            
        success_count = 0
        total_files = len(file_list)
        
        # 创建临时工作文件
        temp_work_file = f"{current_main}.temp"
        
        for i, math_file in enumerate(file_list, 1):
            if not os.path.exists(math_file):
                self.log(f"文件不存在，跳过: {math_file}")
                continue
                
            self.log(f"🔄 正在合并第{i}/{total_files}个文件: {math_file}")
            
            # 复制当前主文档到临时文件
            shutil.copy2(current_main, temp_work_file)
            
            try:
                # 使用题号合并，从1开始
                current_question = success_count + 1
                if self._merge_with_number(temp_work_file, math_file, current_question):
                    # 合并成功，更新主文档
                    shutil.copy2(temp_work_file, current_main)
                    success_count += 1
                    self.log(f"✅ 第{i}个文件合并成功 (题号: {current_question})")
                else:
                    self.log(f"❌ 第{i}个文件合并失败")
            except Exception as e:
                self.log(f"❌ 合并错误: {e}")
                # 保留原始文件，不覆盖
                
        # 清理临时文件
        if os.path.exists(temp_work_file):
            os.remove(temp_work_file)
                
        self.log(f"🎉 合并完成：成功 {success_count}/{total_files} 个文件")
        return success_count == total_files
    
    def _extract_docx(self, docx_file, temp_dir, name):
        """解压Word文档"""
        extract_dir = os.path.join(temp_dir, name)
        with zipfile.ZipFile(docx_file, 'r') as zip_ref:
            zip_ref.extractall(extract_dir)
        return extract_dir
    
    def _analyze_content(self, source_dir):
        """分析文档内容"""
        files = []
        for root, dirs, filenames in os.walk(source_dir):
            for filename in filenames:
                files.append(os.path.join(root, filename))
        
        # 分类统计
        images = [f for f in files if any(ext in f.lower() for ext in ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.wmf', '.emf', '.svg'])]
        math_files = [f for f in files if any(keyword in f.lower() for keyword in ['math', 'equation', 'formula'])]
        embed_files = [f for f in files if 'embed' in f.lower()]
        xml_files = [f for f in files if f.endswith('.xml')]
        
        self.log(f"   📊 内容统计:")
        self.log(f"      🖼️ 图片文件: {len(images)}个")
        self.log(f"      📐 数学相关: {len(math_files)}个")
        self.log(f"      📊 嵌入对象: {len(embed_files)}个")
        self.log(f"      📄 XML文件: {len(xml_files)}个")
        self.log(f"      📁 总文件数: {len(files)}个")
    
    def _merge_documents(self, main_dir, math_dir, question_number=None):
        """合并文档内容"""
        self.log("🔗 开始精确合并...")
        
        # 合并文档XML（带题号）
        self._merge_document_xml(main_dir, math_dir, question_number)
        
        # 修复图片显示问题 - 完整的图片处理流程
        self._fix_image_display(main_dir, math_dir)
        
        # 合并嵌入对象
        self._merge_embedded_objects(main_dir, math_dir)
        
        # 合并数学资源
        self._merge_math_resources(main_dir, math_dir)
        
        # 修复数学公式
        self._fix_math_display(main_dir, math_dir)
        
        self.log("   ✅ 所有内容已精确合并")
    
    def _merge_with_number(self, main_file, math_file, question_number):
        """带题号的合并方法"""
        try:
            # 创建临时目录
            with tempfile.TemporaryDirectory() as temp_dir:
                # 解压两个文档
                main_dir = self._extract_docx(main_file, temp_dir, "main")
                math_dir = self._extract_docx(math_file, temp_dir, "math")
                
                # 分析内容
                self._analyze_content(main_dir)
                self._analyze_content(math_dir)
                
                # 合并文档（带题号）
                self._merge_documents(main_dir, math_dir, question_number)
                
                # 重新打包
                self._create_output(main_dir, main_file)
                
                return True
                
        except Exception as e:
            self.log(f"❌ 合并失败: {e}")
            return False
    
    def _repack_docx(self, source_dir, output_file):
        """重新打包为docx文件"""
        import zipfile
        
        # 确保输出目录存在
        output_dir = os.path.dirname(output_file)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir, exist_ok=True)
        
        # 创建zip文件
        with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 遍历所有文件并添加到zip
            for root, dirs, files in os.walk(source_dir):
                for file in files:
                    file_path = os.path.join(root, file)
                    arcname = os.path.relpath(file_path, source_dir)
                    zipf.write(file_path, arcname)

    def _fix_image_display(self, main_dir, math_dir):
        """修复图片显示问题 - 完整的图片处理"""
        
        # 1. 收集所有媒体文件
        main_media = os.path.join(main_dir, "word", "media")
        math_media = os.path.join(math_dir, "word", "media")
        
        # 确保主文档的media目录存在
        os.makedirs(main_media, exist_ok=True)
        
        # 2. 复制所有图片文件
        image_mapping = {}
        if os.path.exists(math_media):
            for img_file in os.listdir(math_media):
                src_path = os.path.join(math_media, img_file)
                if os.path.isfile(src_path):
                    # 生成新的唯一文件名
                    base_name, ext = os.path.splitext(img_file)
                    counter = 1
                    new_name = img_file
                    
                    # 检查是否已存在，避免覆盖
                    while os.path.exists(os.path.join(main_media, new_name)):
                        new_name = f"{base_name}_{counter}{ext}"
                        counter += 1
                    
                    dest_path = os.path.join(main_media, new_name)
                    shutil.copy2(src_path, dest_path)
                    
                    # 记录映射关系
                    image_mapping[img_file] = new_name
                    self.log(f'📸 复制图片: {img_file} -> {new_name}')
        
        # 确保关系文件存在
        self._ensure_relationships_file_exists(main_dir)
        
        # 2. 修复所有XML文件中的图片引用
        self._update_image_references(main_dir, math_dir, image_mapping)
        
        # 3. 更新关系文件
        self._update_relationship_files(main_dir, math_dir, image_mapping)
        
        # 4. 确保所有图片路径正确
        self._ensure_correct_paths(main_dir, image_mapping)
        
    def _ensure_relationships_file_exists(self, main_dir):
        """确保关系文件总是存在"""
        rels_file = os.path.join(main_dir, 'word', '_rels', 'document.xml.rels')
        os.makedirs(os.path.dirname(rels_file), exist_ok=True)
        
        if not os.path.exists(rels_file):
            rels_content = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
</Relationships>'''
            with open(rels_file, 'w', encoding='utf-8') as f:
                f.write(rels_content)
            self.log('✅ 已创建基础关系文件')

    def _update_image_references(self, main_dir, math_dir, image_mapping=None):
        """更新所有XML文件中的图片引用"""
        
        if image_mapping is None:
            image_mapping = {}
            
            # 获取图片映射
            main_media = os.path.join(main_dir, "word", "media")
            math_media = os.path.join(math_dir, "word", "media")
            
            if os.path.exists(math_media):
                for img_file in os.listdir(math_media):
                    if img_file not in os.listdir(main_media):
                        # 找到对应的新文件名
                        base_name, ext = os.path.splitext(img_file)
                        counter = 1
                        new_name = img_file
                        while os.path.exists(os.path.join(main_media, new_name)):
                            new_name = f"{base_name}_{counter}{ext}"
                            counter += 1
                        image_mapping[img_file] = new_name
                    else:
                        image_mapping[img_file] = img_file
        
        # 需要处理的XML文件
        xml_files = [
            os.path.join(main_dir, 'word', 'document.xml'),
            os.path.join(main_dir, 'word', 'header1.xml'),
            os.path.join(main_dir, 'word', 'header2.xml'),
            os.path.join(main_dir, 'word', 'footer1.xml'),
            os.path.join(main_dir, 'word', 'footer2.xml'),
        ]
        
        for xml_path in xml_files:
            if os.path.exists(xml_path):
                with open(xml_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                original_content = content
                
                # 修复图片引用路径
                # 匹配各种可能的图片路径格式
                patterns = [
                    r'word/media/([^"\']+)',
                    r'../media/([^"\']+)',
                    r'media/([^"\']+)',
                    r'([^"\']*\.png)',
                    r'([^"\']*\.jpg)',
                    r'([^"\']*\.jpeg)',
                    r'([^"\']*\.gif)',
                    r'([^"\']*\.bmp)',
                    r'([^"\']*\.wmf)',
                    r'([^"\']*\.emf)',
                ]
                
                for pattern in patterns:
                    matches = re.findall(pattern, content, re.IGNORECASE)
                    for old_ref in matches:
                        if old_ref in image_mapping:
                            new_ref = image_mapping[old_ref]
                            content = content.replace(old_ref, new_ref)
                
                # 确保所有图片引用都指向正确的相对路径
                content = re.sub(r'([^"\']*/)?media/', 'media/', content)
                
                # 写入更新后的内容
                if content != original_content:
                    with open(xml_path, 'w', encoding='utf-8') as f:
                        f.write(content)
                    self.log(f'✅ 已修复 {os.path.basename(xml_path)} 中的图片引用')

    def _update_relationship_files(self, main_dir, math_dir, image_mapping=None):
        """更新关系文件中的图片引用 - 修复版本"""
        
        if image_mapping is None:
            image_mapping = {}
            
            # 获取图片映射
            main_media = os.path.join(main_dir, "word", "media")
            math_media = os.path.join(math_dir, "word", "media")
            
            if os.path.exists(math_media):
                for img_file in os.listdir(math_media):
                    src_path = os.path.join(math_media, img_file)
                    if os.path.isfile(src_path):
                        # 生成新的唯一文件名
                        base_name, ext = os.path.splitext(img_file)
                        counter = 1
                        new_name = img_file
                        
                        # 检查是否已存在，避免覆盖
                        while os.path.exists(os.path.join(main_media, new_name)):
                            new_name = f"{base_name}_{counter}{ext}"
                            counter += 1
                        
                        image_mapping[img_file] = new_name
        
        # 主文档的关系文件
        main_rels = os.path.join(main_dir, 'word', '_rels', 'document.xml.rels')
        math_rels = os.path.join(math_dir, 'word', '_rels', 'document.xml.rels')
        
        if not os.path.exists(math_rels):
            return
        
        # 读取数学文档的关系文件
        with open(math_rels, 'r', encoding='utf-8') as f:
            math_rels_content = f.read()
        
        # 解析关系文件，获取图片关系
        import xml.etree.ElementTree as ET
        try:
            math_root = ET.fromstring(math_rels_content)
        except ET.ParseError:
            # 如果解析失败，使用正则表达式提取
            math_relations = re.findall(r'<Relationship[^>]*Target="([^"]*)"[^>]*Type="([^"]*)"[^>]*Id="([^"]*)"[^>]*>', math_rels_content)
        else:
            math_relations = []
            for child in math_root:
                target = child.get('Target', '')
                rel_type = child.get('Type', '')
                rel_id = child.get('Id', '')
                if 'image' in rel_type.lower() or 'media' in target.lower():
                    math_relations.append((target, rel_type, rel_id))
        
        # 确保关系文件存在
        os.makedirs(os.path.dirname(main_rels), exist_ok=True)
        
        # 获取主文档的关系文件内容
        if os.path.exists(main_rels):
            with open(main_rels, 'r', encoding='utf-8') as f:
                main_rels_content = f.read()
            
            # 确保有正确的XML结构
            if '</Relationships>' not in main_rels_content:
                main_rels_content = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n</Relationships>'
        else:
            main_rels_content = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n</Relationships>'
        
        # 处理图片关系
        for old_target, rel_type, rel_id in math_relations:
            # 获取文件名
            old_filename = os.path.basename(old_target)
            
            # 查找映射的新文件名
            new_filename = image_mapping.get(old_filename, old_filename)
            new_target = f"media/{new_filename}"
            
            # 检查这个关系是否已经存在
            if new_target not in main_rels_content:
                # 生成新的关系ID
                new_rel_id = self._generate_unique_rel_id(main_rels_content, rel_id)
                
                # 创建新的关系
                new_rel = f'<Relationship Id="{new_rel_id}" Type="{rel_type}" Target="{new_target}"/>'
                
                # 插入到关系文件中
                insert_pos = main_rels_content.rfind('</Relationships>')
                if insert_pos != -1:
                    main_rels_content = main_rels_content[:insert_pos] + '  ' + new_rel + '\n' + main_rels_content[insert_pos:]
                    
                    # 同时更新document.xml中的引用
                    self._update_document_references(main_dir, rel_id, new_rel_id)
                    
                    self.log(f'🔗 添加图片关系: {new_rel_id} -> {new_target}')
        
        # 写入更新后的关系文件
        with open(main_rels, 'w', encoding='utf-8') as f:
            f.write(main_rels_content)
        
        self.log('✅ 已更新关系文件中的图片引用')

    def _generate_unique_rel_id(self, content, base_id):
        """生成唯一的关系ID"""
        counter = 1
        new_id = base_id
        
        # 提取数字部分
        match = re.search(r'(\d+)$', base_id)
        if match:
            base_num = int(match.group(1))
            counter = base_num + 1
            new_id = re.sub(r'\d+$', str(counter), base_id)
        
        while f'Id="{new_id}"' in content:
            new_id = f"rId{counter}"
            counter += 1
            
        return new_id

    def _update_document_references(self, main_dir, old_rel_id, new_rel_id):
        """更新document.xml中的关系引用"""
        doc_xml = os.path.join(main_dir, 'word', 'document.xml')
        if os.path.exists(doc_xml):
            with open(doc_xml, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 更新r:embed引用
            content = content.replace(f'r:embed="{old_rel_id}"', f'r:embed="{new_rel_id}"')
            content = content.replace(f'r:id="{old_rel_id}"', f'r:id="{new_rel_id}"')
            
            with open(doc_xml, 'w', encoding='utf-8') as f:
                f.write(content)

    def _ensure_correct_paths(self, main_dir, image_mapping):
        """确保所有图片路径完全正确"""
        
        # 1. 修复document.xml中的路径
        doc_xml = os.path.join(main_dir, 'word', 'document.xml')
        if os.path.exists(doc_xml):
            with open(doc_xml, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 确保所有图片引用使用正确的相对路径
            content = re.sub(r'word/media/', 'media/', content)
            content = re.sub(r'../media/', 'media/', content)
            
            # 确保所有r:embed引用正确
            content = re.sub(r'r:embed="([^"]*)/media/', r'r:embed="', content)
            content = re.sub(r'r:embed="([^"]*)"', lambda m: f'r:embed="{m.group(1).split("/")[-1]}"' if '/' in m.group(1) else m.group(0), content)
            
            with open(doc_xml, 'w', encoding='utf-8') as f:
                f.write(content)
            self.log('✅ 已修复document.xml中的图片路径')
        
        # 2. 确保关系文件中的路径完全匹配实际文件
        rels_file = os.path.join(main_dir, 'word', '_rels', 'document.xml.rels')
        if os.path.exists(rels_file):
            with open(rels_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 确保所有Target路径都指向存在的文件
            media_dir = os.path.join(main_dir, 'word', 'media')
            actual_files = os.listdir(media_dir) if os.path.exists(media_dir) else []
            
            for old_name, new_name in image_mapping.items():
                if new_name in actual_files:
                    content = content.replace(f'media/{old_name}', f'media/{new_name}')
            
            # 确保所有路径都是正确的相对路径
            content = re.sub(r'Target="[^"]*word/media/', 'Target="media/', content)
            content = re.sub(r'Target="[^"]*../media/', 'Target="media/', content)
            
            with open(rels_file, 'w', encoding='utf-8') as f:
                f.write(content)
            self.log('✅ 已确保关系文件路径完全匹配')
    
    def set_auto_cleanup(self, enabled):
        """设置是否自动清理备份文件
        
        Args:
            enabled (bool): True启用自动清理，False禁用
        """
        self.auto_cleanup = enabled
        self.log(f"🧹 自动清理备份文件: {'启用' if enabled else '禁用'}")
    
    def cleanup_all_backups(self):
        """手动清理所有备份文件"""
        self.log("🧹 开始手动清理所有备份文件...")
        self._cleanup_backup_files()
    
    def cleanup_backup_for(self, base_file):
        """手动清理特定文件的备份
        
        Args:
            base_file (str): 要清理备份的文件路径
        """
        if os.path.exists(base_file):
            self.log(f"🧹 清理 {base_file} 的备份文件...")
            self._cleanup_backup_files(base_file)

    def _merge_media_files(self, main_dir, math_dir):
        """合并媒体文件（已集成到图片修复中）"""
        pass  # 功能已集成到 _fix_image_display
        
        # 合并嵌入对象
        self._merge_embedded_objects(main_dir, math_dir)
        
        # 合并数学资源
        self._merge_math_resources(main_dir, math_dir)
        
        # 修复数学公式
        self._fix_math_display(main_dir, math_dir)
        
        self.log("   ✅ 所有内容已精确合并")
    
    def _merge_document_xml(self, main_dir, math_dir, question_number=None):
        """合并文档XML内容"""
        main_xml = os.path.join(main_dir, "word", "document.xml")
        math_xml = os.path.join(math_dir, "word", "document.xml")
        
        if not os.path.exists(main_xml) or not os.path.exists(math_xml):
            raise Exception("找不到document.xml文件")
        
        # 读取内容
        with open(main_xml, 'r', encoding='utf-8') as f:
            main_content = f.read()
        with open(math_xml, 'r', encoding='utf-8') as f:
            math_content = f.read()
        
        # 修复命名空间
        main_content = self._ensure_math_namespace(main_content)
        math_content = self._ensure_math_namespace(math_content)
        
        # 提取body内容
        math_body_content = self._extract_body_content(math_content)
        math_body_content = self._fix_math_formulas(math_body_content)
        
        # 添加题号（与题目在同一行）
        if question_number is not None:
            # 使用Word XML格式插入题号到第一个段落
            import re
            
            # 查找第一个<w:p>标签
            p_start = math_body_content.find('<w:p')
            if p_start != -1:
                # 找到第一个段落
                p_end = math_body_content.find('>', p_start) + 1
                
                # 创建题号的XML
                question_xml = f'<w:r><w:t>{question_number}. </w:t></w:r>'
                
                # 插入题号到段落开头
                math_body_content = (
                    math_body_content[:p_end] + 
                    question_xml + 
                    math_body_content[p_end:]
                )
            else:
                # 如果没有段落，创建新段落
                question_xml = f'<w:p><w:r><w:t>{question_number}. </w:t></w:r></w:p>'
                math_body_content = question_xml + math_body_content
        
        # 合并内容
        body_end_pos = main_content.rfind('</w:body>')
        if body_end_pos == -1:
            body_end_pos = main_content.rfind('</w:body')
        
        # 完全干净的合并，无提示信息和分隔符
        new_content = (
            main_content[:body_end_pos] + 
            math_body_content + 
            main_content[body_end_pos:]
        )
        
        with open(main_xml, 'w', encoding='utf-8') as f:
            f.write(new_content)
        
        self.log("   ✅ 文档内容已合并")
    
    def _merge_media_files(self, main_dir, math_dir):
        """合并媒体文件"""
        main_media = os.path.join(main_dir, "word", "media")
        math_media = os.path.join(math_dir, "word", "media")
        
        if os.path.exists(math_media):
            if not os.path.exists(main_media):
                shutil.copytree(math_media, main_media)
            else:
                self._merge_directories(math_media, main_media)
            self.log("   ✅ 媒体文件已合并")
    
    def _merge_embedded_objects(self, main_dir, math_dir):
        """合并嵌入对象"""
        main_objects = os.path.join(main_dir, "word", "embeddings")
        math_objects = os.path.join(math_dir, "word", "embeddings")
        
        if os.path.exists(math_objects):
            if not os.path.exists(main_objects):
                shutil.copytree(math_objects, main_objects)
            else:
                self._merge_directories(math_objects, main_objects)
            self.log("   ✅ 嵌入对象已合并")
    
    def _merge_math_resources(self, main_dir, math_dir):
        """合并数学资源"""
        self._copy_math_formulas(main_dir, math_dir)
    
    def _fix_math_display(self, main_dir, math_dir):
        """修复数学公式显示"""
        self.log("   ✅ 数学公式显示已修复")
    
    def _ensure_math_namespace(self, content):
        """确保数学命名空间"""
        if 'xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"' not in content:
            content = content.replace(
                '<w:document',
                '<w:document xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"'
            )
        return content
    
    def _extract_body_content(self, content):
        """提取body内容"""
        start = content.find('<w:body')
        end = content.rfind('</w:body>')
        
        if start == -1 or end == -1:
            return ""
        
        start = content.find('>', start) + 1
        return content[start:end]
    
    def _fix_math_formulas(self, content):
        """修复数学公式"""
        # 修复数学标签
        replacements = [
            (r'<(oMath)(?![^>]*xmlns)', r'<m:\1'),
            (r'<(oMathPara)(?![^>]*xmlns)', r'<m:\1'),
            (r'<(acc|bar|box|borderBox|d|eqArr|f|func|groupChr)', r'<m:\1'),
            (r'<(limLow|limUpp|m|nary|phant|rad|sPre|sSub|sSubSup|sSup)', r'<m:\1'),
            (r'<(r|t|rPr|tPr)', r'<m:\1'),
        ]
        
        for pattern, replacement in replacements:
            content = re.sub(pattern, replacement, content)
        
        return content
    

    
    def _merge_directories(self, source, target):
        """安全合并目录"""
        if not os.path.exists(source):
            return
        
        if not os.path.exists(target):
            shutil.copytree(source, target)
            return
        
        for item in os.listdir(source):
            source_item = os.path.join(source, item)
            target_item = os.path.join(target, item)
            
            if os.path.isfile(source_item):
                if not os.path.exists(target_item):
                    shutil.copy2(source_item, target_item)
                else:
                    # 重命名避免冲突
                    base, ext = os.path.splitext(item)
                    counter = 1
                    while os.path.exists(target_item):
                        new_name = f"{base}_{counter}{ext}"
                        target_item = os.path.join(target, new_name)
                        counter += 1
                    shutil.copy2(source_item, target_item)
            elif os.path.isdir(source_item):
                self._merge_directories(source_item, target_item)
    
    def _copy_math_formulas(self, main_dir, math_dir):
        """拷贝数学公式相关资源"""
        math_resources = [
            "word/math",
            "word/embeddings", 
            "word/media",
            "customXml",
        ]
        
        for resource_path in math_resources:
            source_path = os.path.join(math_dir, resource_path)
            target_path = os.path.join(main_dir, resource_path)
            
            if os.path.exists(source_path):
                if not os.path.exists(target_path):
                    shutil.copytree(source_path, target_path)
                else:
                    self._merge_directories(source_path, target_path)
        
        # 合并关系文件
        rels_files = [
            "word/_rels/document.xml.rels",
            "word/_rels/styles.xml.rels",
        ]
        
        for rels_file in rels_files:
            source_file = os.path.join(math_dir, rels_file)
            target_file = os.path.join(main_dir, rels_file)
            
            if os.path.exists(source_file):
                os.makedirs(os.path.dirname(target_file), exist_ok=True)
                self._merge_xml_files(source_file, target_file)
    
    def _merge_xml_files(self, source_file, target_file):
        """合并XML文件"""
        if not os.path.exists(source_file):
            return
        
        if not os.path.exists(target_file):
            shutil.copy2(source_file, target_file)
            return
        
        try:
            with open(source_file, 'r', encoding='utf-8') as f:
                source_content = f.read()
            with open(target_file, 'r', encoding='utf-8') as f:
                target_content = f.read()
            
            # 合并关系
            if 'Relationship' in source_content and 'Relationship' in target_content:
                source_rels = re.findall(r'<Relationship[^>]*>', source_content)
                for rel in source_rels:
                    if rel not in target_content:
                        target_content = target_content.replace('</Relationships>', rel + '\n</Relationships>')
                
                with open(target_file, 'w', encoding='utf-8') as f:
                    f.write(target_content)
        except Exception:
            # 如果处理失败，直接覆盖
            shutil.copy2(source_file, target_file)
    
    def cleanup_backups(self, main_file=None):
        """清理旧的备份文件"""
        if not main_file:
            # 默认清理当前目录下所有.docx.backup文件
            backup_files = Path(self.workspace).glob('*.docx.backup')
        else:
            # 清理指定主文件的备份
            backup_files = [Path(f'{main_file}.backup')]
        
        deleted_count = 0
        for backup in backup_files:
            if backup.exists():
                try:
                    os.remove(backup)
                    deleted_count += 1
                    self.log(f'🗑️ 已删除备份文件: {backup.name}')
                except Exception as e:
                    self.log(f'⚠️ 无法删除备份 {backup.name}: {str(e)}')
        
        self.log(f'✅ 清理完成，共删除 {deleted_count} 个备份文件')
        
    def _create_output(self, source_dir, output_file):
        """创建输出文件"""
        with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as zip_ref:
            for root, dirs, files in os.walk(source_dir):
                for file in files:
                    file_path = os.path.join(root, file)
                    arc_name = os.path.relpath(file_path, source_dir)
                    zip_ref.write(file_path, arc_name)


# 使用示例和测试代码
if __name__ == "__main__":
    """
    使用示例：
    
    # 基本用法
    merger = WordMathMerger()
    merger.merge("main.docx", "math.docx")
    
    # 高级用法
    merger = WordMathMerger(backup=True, verbose=True)
    merger.merge_files("main.docx", "math.docx", "result.docx")
    
    # 合并文件列表
    merger = WordMathMerger()
    files = ["math1.docx", "math2.docx", "math3.docx"]
    merger.merge_list("main.docx", files, "merged_all.docx")
    """
    
    # 命令行用法
    if len(sys.argv) >= 3:
        main_file = sys.argv[1]
        math_file = sys.argv[2]
        output_file = sys.argv[3] if len(sys.argv) > 3 else None
        
        merger = WordMathMerger()
        merger.merge(main_file, math_file, output_file)
    else:
        # 默认用法
        merger = WordMathMerger()
        merger.merge("main.docx", "math.docx")